介绍
适配器(Adapter)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
适配器模式在我们开发中使用率极高,从代码中随处可见的 Adapter 可以判断出来。从最早的 ListView、GridView 到现在最新的 RecyclerView 都需要使用 Adapter。说到底,适配器是将两个不兼容的类融合在一起,它有点像粘合剂,将不同的东西通过一种转换使得它们能够协作起来。
优点
- 更好的复用性。系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
- 更好的扩展性。在实现适配器功能的时候,可以调用自己开发的工功能,从而自然地扩展系统的功能。
缺点
- 过多地使用适配器,会让系统非常零乱,不易整体把握。
使用场景
- 当想使用一个已经存在的类,但它的接口不符合需求时。
- 当想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作。
- 需要一个统一的输出接口,而输入端的类型不可预知。
结构与实现
类适配器模式可采用多重继承方式实现,如 C++ 可定义一个适配器类来同时继承当前系统的业务接口和现有组件库中已经存在的组件接口;Java 不支持多继承,但可以定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。
对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。现在来介绍它们的基本结构。
模式包含以下主要角色。
- Target:目标接口,当前系统业务所期待的接口,它可以是抽象类或接口。
- Adaptee:适配者类,它是被访问和适配的现存组件库中的组件接口。
- Adapter:适配器类,它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
其结构图如下图所示。
类适配器模式的代码如下:
对象适配器模式的代码如下:
说明:对象适配器模式中的“目标接口”和“适配者类”的代码同类适配器模式一样,只要修改适配器类和客户端的代码即可。与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到 Adaptee 类,而是使用代理关系。
示例
用电源接口做例子,笔记本电脑的电源一般在 5V 电压,但是在我们生活中的电线电压一般是 220V。这个时候出现了不匹配的状况,在软件开发中称为接口不兼容,此时就需要适配器来进行一个接口转换。此时需要用一个 Adapter 层来进行接口转换。即:5V 电压就是 Target 接口,220V 电压就是 Adaptee 类,而将电压从 220V 转换到 5V 就是 Adapter。
- 类适配器模式。
|
|
- 对象适配器模式。
Target 和 Adaptee 同上,但 Adapter 类不继承 Adaptee 类,而是代理,这比类适配器方式更为灵活。
|
|
ANDROID 源码中的实现
在开发过程中,ListView 的 Adapter 是我们最常见的类型之一。ListView 中并没有 Adapter 相关的成员变量,其实 Adapter 在 ListView 的父类 AbsListView 中,AbsListView 是一个列表控件的抽象。
ListView 实现了 layoutChildren 方法,代码如下:
ListView 覆写了 AbsListView 中的 layoutChildren 函数,在该函数中根据布局模式来布局 item view,例如,默认情况是从上到下开始布局,但是,也有从下到上开始布局的,例如 QQ 聊天窗口的气泡布局,最新的消息就会布局到窗口的最底部。
makeAndAddView 方法如下:
makeAndAddView 分为两个步骤,第一个是根据 position 获取一个 item view,然后将这个 view 布局到特定的位置。获取一个 item view 调用的是 obtainView 方法。这个方法在 AbsListView 中。
obtainView 方法定义了列表控件的 item view 的复用逻辑,首先会从 RecyclerBin 中获取一个缓存的 View。如果有缓存则将这个缓存的 View 传递到 Adapter 的 getView 的第二个参数中,这也就是我们对 Adapter 的最常见的优化方式,即判断 getView 的 convertView 是否为空。如果为空则从 xml 中创建视图,否则使用缓存的 View。这样避免了每次都从 xml 加载布局的消耗,能够显著提升 ListView 的效率。
在 ListView 的适配器模式中,target 角色就是 View,Adapter 就是将 item view 输出为 view 抽象的角色,adaptee 就是需要被处理的 item view。通过增加 adapter 一层来将 item view 的操作抽象起来,listView 等集合视图通过 adapter 对象获得 item 的个数、数据、item view 等,从而达到适配各种数据、各种 item 视图的效果。